using System;
using System.Text;
using System.Runtime.InteropServices;

using SqInterface.Utils;
using SqInterface.InteropServices;

namespace SqInterface
{

// typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM);
// typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size);
// typedef void      (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/);
// typedef void      (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...);
// typedef void      (*SQDEBUGHOOK)(HSQUIRRELVM /*v*/, SQInteger /*type*/, const SQChar * /*sourcename*/, SQInteger /*line*/, const SQChar * /*funcname*/);
// typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger);
// typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger);
// typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer);

	public class SqObjectType
	{
		#region Internal Definitions
		private const int  _RT_NULL			= 0x00000001;
		private const int  _RT_INTEGER		= 0x00000002;
		private const int  _RT_FLOAT		= 0x00000004;
		private const int  _RT_BOOL			= 0x00000008;
		private const int  _RT_STRING		= 0x00000010;
		private const int  _RT_TABLE		= 0x00000020;
		private const int  _RT_ARRAY		= 0x00000040;
		private const int  _RT_USERDATA		= 0x00000080;
		private const int  _RT_CLOSURE		= 0x00000100;
		private const int  _RT_NATIVECLOSURE= 0x00000200;
		private const int  _RT_GENERATOR	= 0x00000400;
		private const int  _RT_USERPOINTER	= 0x00000800;
		private const int  _RT_THREAD		= 0x00001000;
		private const int  _RT_FUNCPROTO	= 0x00002000;
		private const int  _RT_CLASS		= 0x00004000;
		private const int  _RT_INSTANCE		= 0x00008000;
		private const int  _RT_WEAKREF		= 0x00010000;

		private const int  SQOBJECT_REF_COUNTED	= 0x08000000;
		private const int  SQOBJECT_NUMERIC		= 0x04000000;
		private const int  SQOBJECT_DELEGABLE	= 0x02000000;
		private const int  SQOBJECT_CANBEFALSE	= 0x01000000;
		#endregion

		#region Object Type Definitions
		public const int OT_NULL =			(_RT_NULL|SQOBJECT_CANBEFALSE);
		public const int OT_INTEGER =		(_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE);
		public const int OT_FLOAT =			(_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE);
		public const int OT_BOOL =			(_RT_BOOL|SQOBJECT_CANBEFALSE);
		public const int OT_STRING =		(_RT_STRING|SQOBJECT_REF_COUNTED);
		public const int OT_TABLE =			(_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE);
		public const int OT_ARRAY =			(_RT_ARRAY|SQOBJECT_REF_COUNTED);
		public const int OT_USERDATA =		(_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE);
		public const int OT_CLOSURE =		(_RT_CLOSURE|SQOBJECT_REF_COUNTED);
		public const int OT_NATIVECLOSURE =	(_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED);
		public const int OT_GENERATOR =		(_RT_GENERATOR|SQOBJECT_REF_COUNTED);
		public const int OT_USERPOINTER =	_RT_USERPOINTER;
		public const int OT_THREAD =		(_RT_THREAD|SQOBJECT_REF_COUNTED);
		public const int OT_FUNCPROTO =		(_RT_FUNCPROTO|SQOBJECT_REF_COUNTED); //internal usage only
		public const int OT_CLASS =			(_RT_CLASS|SQOBJECT_REF_COUNTED);
		public const int OT_INSTANCE =		(_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE);
		public const int OT_WEAKREF =		(_RT_WEAKREF|SQOBJECT_REF_COUNTED);
		#endregion

		#region Convenience Methods
		public static string GetTypeName( int SquirrelType )
		{
			string temp = "unknown";
			switch ( SquirrelType )
			{
				case SqObjectType.OT_ARRAY:
					return "array";
				case SqObjectType.OT_BOOL:
					return "bool";
				case SqObjectType.OT_CLASS:
					return "class";
				case SqObjectType.OT_FLOAT:
					return "float";
				case SqObjectType.OT_FUNCPROTO:
					return "funcproto";
				case SqObjectType.OT_GENERATOR:
					return "generator";
				case SqObjectType.OT_INSTANCE:
					return "instance";
				case SqObjectType.OT_INTEGER:
					return "integer";
				case SqObjectType.OT_NATIVECLOSURE:
					return "nativeclosure";
				case SqObjectType.OT_NULL:
					return "null";
				case SqObjectType.OT_STRING:
					return "string";
				case SqObjectType.OT_TABLE:
					return "table";
				case SqObjectType.OT_THREAD:
					return "thread";
				case SqObjectType.OT_USERDATA:
					return "userdata";
				case SqObjectType.OT_USERPOINTER:
					return "userpointer";
				case SqObjectType.OT_WEAKREF:
					return "weakref";
			}
			return temp;
		}
		#endregion
	}
    
    /// <summary>
    /// Definition of an SqLexReadFunction
    /// </summary>
    /// <param name="valuePtr"></param>
    /// <returns></returns>
    /// 
    public delegate int SqLexReadFunction(IntPtr valuePtr);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void SqApiCompatiblePrintFunction(StringBuilder buffer);

    // definitions used by the squirrel interop API
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    internal delegate int SqAPIExReaderFunction(IntPtr data);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    internal delegate int SqAPIReaderDelegate(IntPtr vm, IntPtr data, int i1);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    internal delegate void SqAPICompilerErrorDelegate(IntPtr vm, string desc, int Line, int Column);
    
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    internal delegate int SqAPIMethodDelegate(IntPtr vm);

	/// <summary>
	/// Summary description for SqDLL.
	/// </summary>
	public class SqAPI	
	{
		const string SQDLL = "sqdll.dll";

		#region Virtual Machine

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern IntPtr SqClose( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern IntPtr SqGetForeignPointer( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern IntPtr SqGetPrintFunc( IntPtr vm );

        [DllImport(SQDLL, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr SqGetErrorFunc(IntPtr vm);

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetVMState( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqMove( IntPtr TargetVM, IntPtr SourceVM, int idx );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern IntPtr SqOpen( int InitialStackSize );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern IntPtr SqNewThread( IntPtr friendVM, int InitialStackSize );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPushRegisteryTable( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPushRootTable( IntPtr vm );
		
		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqSetErrorHandler( IntPtr vm );
		
		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqSetForeignPtr( IntPtr vm, IntPtr p );
		
		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
        public static extern void SqSetPrintFunc(IntPtr vm, IntPtr prnFn, IntPtr errFn);

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqSetRootTable( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqSuspendVM( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqWakeUpVM( IntPtr vm, bool ResumedRet, bool RetVal );

		#endregion

		#region Compiler Related Methods

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
        internal static extern void SqCompileReader(IntPtr vm, SqAPIExReaderFunction ExReaderFunc, IntPtr UserPtr, string SourceName, bool RaiseError);

        [DllImport(SQDLL, CallingConvention = CallingConvention.Cdecl)]
        internal static extern void SqCompileBuffer(IntPtr vm, IntPtr ExReaderFunc, IntPtr UserPtr, string SourceName, bool RaiseError);

		internal static MulticastDelegate CreateCompatibleDelegate( SqAPIMethodDelegate method )
		{
			return DelegateGenerator.CreateDelegate( method, 
				System.Runtime.InteropServices.CallingConvention.Cdecl );
		}
		internal static MulticastDelegate CreateCompatibleDelegate( SqReaderDelegate method )
		{
			return DelegateGenerator.CreateDelegate( method, 
				System.Runtime.InteropServices.CallingConvention.Cdecl );
		}

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqCompileBuffer( IntPtr vm, String Buffer, int IntSize, string SourceName, bool RaiseError );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqEnableDebugInfo( IntPtr vm, bool DebugInfo );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
        public static extern void SqSetCompilerErrorHandler(IntPtr vm, IntPtr ptr);

		#endregion

		#region Stack Operations

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqCmp( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetTop( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPop( IntPtr vm, int Count );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPopTop( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPush( IntPtr vm, int Count );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqRemove( IntPtr vm, int Count );
		
		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqReserveStack( IntPtr vm, int Count );
				
		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqSetTop( IntPtr vm, int Count );

		#endregion

		#region Object Creation and Handling

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqCreateInstance( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetBool( IntPtr vm, int Index, ref bool Result );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetClosureInfo( IntPtr vm, int Index, ref uint nparams, ref uint nfreevars );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetFloat( IntPtr vm, int Index, ref float Result );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetInstanceUp( IntPtr vm, int Index, ref IntPtr up, IntPtr TypeTag );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetInteger( IntPtr vm, int Index, ref int Result );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern IntPtr SqGetScratchpad( IntPtr vm, int MinSize );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetSize( IntPtr vm, int Index );

		// FIXME: Will this "just work"?
		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetString( IntPtr vm, int Index, ref IntPtr result );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetThread( IntPtr vm, int Index, ref IntPtr result );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetType( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetTypeTag( IntPtr vm, int Index, ref IntPtr TypeTag );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetUserData( IntPtr vm, int Index, ref IntPtr UserPtr, ref IntPtr TypeTag );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetUserPointer( IntPtr vm, int Index, ref IntPtr UserPtr );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqNewArray( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqNewClass( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqNewClosure( IntPtr vm, MulticastDelegate func, int nfreevars );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqNewTable( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern IntPtr SqNewUserData( IntPtr vm, uint size );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPushBool( IntPtr vm, bool Value );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPushFloat( IntPtr vm, float Value );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPushInteger( IntPtr vm, int Value );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPushNull( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPushString( IntPtr vm, string Value, int len );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPushUserPointer( IntPtr vm, IntPtr Value );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqSetInstanceUp( IntPtr vm, int Index, IntPtr up );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqSetNativeClosureName( IntPtr vm, int Index, string name );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqSetParamsCheck( IntPtr vm, int nparamscheck, string typemask);

		// FIXME:SHould be a delegate call here
		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqSetReleaseHook( IntPtr vm, int Index, IntPtr hook);

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqSetTypeTag( IntPtr vm, int Index, IntPtr typetag);

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqCall( IntPtr vm, int _params, bool retval, bool raiseError );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqGetLastError( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern string SqGetLastError( IntPtr vm, uint level );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqResetError( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqResume( IntPtr vm, bool retval, bool raiseError );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqThrowError( IntPtr vm, string err );

		#endregion

		#region Objects Manipulation

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqArrayAppend( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqArrayPop( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqArrayResize( IntPtr vm, int Index, int newsize );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqArrayReverse( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqClone( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqCreateSlot( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqDeleteSlot( IntPtr vm, int Index, bool pushval );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGet( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetAttributes( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetClass( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetDelegate( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern string SqGetFreeVariable( IntPtr vm, int Index, int nval );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetWeakRefVal( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqNext( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqRawDeleteSlot( IntPtr vm, int Index, bool pushval );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqRawGet( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqRawSet( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqSet( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqSetAttributes( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqSetDelegate( IntPtr vm, int Index );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqSetFreeVariable( IntPtr vm, int Index, int nval );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqWeakRef( IntPtr vm, int Index );

		#endregion

		#region ByteCode Serialization

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqReadClosure( IntPtr vm, IntPtr ReadFunc, IntPtr up );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqWriteClosure( IntPtr vm, IntPtr WriteFunc, IntPtr up );

		#endregion

		#region Raw Object Handling

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqAddRef( IntPtr vm, IntPtr po );
		
		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetObjTypeTag( IntPtr vm, ref IntPtr typetag );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqGetStackObj( IntPtr vm, int Index, ref IntPtr po );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern bool SqObjToBool( ref IntPtr SqObj ) ;

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern float SqObjToFloat( ref IntPtr SqObj ) ;

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern int SqObjToInteger( ref IntPtr SqObj ) ;

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern string SqObjToString( ref IntPtr SqObj ) ;

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqPushObject( IntPtr SqObj ) ;

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqRelease( IntPtr vm, ref IntPtr SqObj ) ;

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqResetObject( ref IntPtr SqObj ) ;

		#endregion

		#region Debug Interface
	
		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqSetDebugHook( IntPtr vm );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern void SqStackInfos( IntPtr vm, int level, ref IntPtr si );

		#endregion

        #region Success and Failed
        [DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern bool SqSuccess( int result );

		[DllImport(SQDLL,CallingConvention=CallingConvention.Cdecl)]
		public static extern bool SqFailed( int result );
        #endregion

        #region CLR Compatible Print Functions
        [DllImport(SQDLL, CallingConvention = CallingConvention.Cdecl)]
        public static extern int SqSetCompatiblePrintFunctions(IntPtr vm, IntPtr fnPrintDelegate, IntPtr fnErrorDelegate);

        [DllImport(SQDLL, CallingConvention = CallingConvention.Cdecl)]
        public static extern int SqSetCompatiblePrintFunction(IntPtr vm, IntPtr fnPrintDelegate);

        [DllImport(SQDLL, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr SqGetCompatiblePrintFunction(IntPtr vm);

        [DllImport(SQDLL, CallingConvention = CallingConvention.Cdecl)]
        public static extern int SqSetCompatibleErrorFunction(IntPtr vm, IntPtr fnPrintDelegate);

        [DllImport(SQDLL, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr SqGetCompatibleErrorFunction(IntPtr vm);
        #endregion
    }
}
